package com.ryskoo.config.shiro;

import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfiguration {

	/*
	 * @Bean public FilterRegistrationBean delegatingFilterProxy() {
	 * FilterRegistrationBean filterRegistrationBean = new
	 * FilterRegistrationBean(); // DelegatingFilterProxy proxy = new
	 * DelegatingFilterProxy(); // proxy.setTargetFilterLifecycle(true); //
	 * proxy.setTargetBeanName("shiroFilter"); //
	 * filterRegistrationBean.setFilter(proxy);
	 * 
	 * EnumSet<DispatcherType> dispatcherTypes = EnumSet
	 * .allOf(DispatcherType.class);
	 * dispatcherTypes.create(DispatcherType.REQUEST);
	 * dispatcherTypes.create(DispatcherType.FORWARD);
	 * dispatcherTypes.create(DispatcherType.INCLUDE);
	 * dispatcherTypes.create(DispatcherType.ERROR);
	 * 
	 * filterRegistrationBean.setDispatcherTypes(dispatcherTypes);
	 * 
	 * return filterRegistrationBean; }
	 */

	/**
	 * ShiroFilterFactoryBean 处理拦截资源文件问题。
	 * 注意：单独一个ShiroFilterFactoryBean配置是或报错的，以为在
	 * 初始化ShiroFilterFactoryBean的时候需要注入：SecurityManager
	 *
	 * Filter Chain定义说明 1、一个URL可以配置多个Filter，使用逗号分隔 2、当设置多个过滤器时，全部验证通过，才视为通过
	 * 3、部分过滤器可指定参数，如perms，roles
	 *
	 */
	@Bean
	public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
		ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

		// 必须设置 SecurityManager
		shiroFilterFactoryBean.setSecurityManager(securityManager);

		// 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
		shiroFilterFactoryBean.setLoginUrl("/tologin");

		// 登录成功后要跳转的链接
		shiroFilterFactoryBean.setSuccessUrl("/index");

		// 未授权，跳转到未授权界面;
		shiroFilterFactoryBean.setUnauthorizedUrl("/error/unauthorize");

		// 权限控制map.
		Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
		// 配置不会被拦截的链接 顺序判断
		// 配置退出过滤器,其中的具体的退出代码Shiro已经替我们实现了

		filterChainDefinitionMap.put("/logout", "logout");
		// tologin和login，不需要认证
		filterChainDefinitionMap.put("/tologin", "anon");
		filterChainDefinitionMap.put("/login", "anon");

		// 后台所有的其他页面必须经过认证
		filterChainDefinitionMap.put("/vendor/**", "authc");

		shiroFilterFactoryBean
				.setFilterChainDefinitionMap(filterChainDefinitionMap);
		return shiroFilterFactoryBean;
	}

	@Bean
	public SecurityManager securityManager() {
		DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
		// 设置realm.
		securityManager.setRealm(managerShiroRealm());
		// 自定义缓存实现 使用redis
		securityManager.setCacheManager(getCacheManager());
		// 自定义session管理 使用redis
		securityManager.setSessionManager(sessionManager());
		// 注入记住我管理器;
		// securityManager.setRememberMeManager(rememberMeManager());
		return securityManager;
	}

	/**
	 * 凭证匹配器 （由于我们的密码校验交给Shiro的SimpleAuthenticationInfo进行处理了 ）
	 * 
	 * @return
	 */
	@Bean
	public HashedCredentialsMatcher hashedCredentialsMatcher() {
		HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
		hashedCredentialsMatcher.setHashAlgorithmName("md5");// 散列算法:这里使用MD5算法;
		hashedCredentialsMatcher.setHashIterations(1);// 散列的次数，比如散列两次，相当于
														// md5(md5(""));
		return hashedCredentialsMatcher;
	}

	@Bean
	public ManagerRealm managerShiroRealm() {
		ManagerRealm managerrealm = new ManagerRealm();
		managerrealm.setCacheManager(getCacheManager());
		managerrealm.setCredentialsMatcher(hashedCredentialsMatcher());
		return managerrealm;
	}

	// 自定义sessionManager
	@Bean
	public DefaultWebSessionManager sessionManager() {
		DefaultWebSessionManager shiroSessionManager = new DefaultWebSessionManager();
		shiroSessionManager.setSessionDAO(redisSessionDAO());
		return shiroSessionManager;
	}

	/**
	 * RedisSessionDAO shiro sessionDao层的实现 通过redis
	 */
	@Bean
	public RedisSessionDAO redisSessionDAO() {
		RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
		return redisSessionDAO;
	}

	/**
	 * 开启shiro aop注解支持. 使用代理方式;所以需要开启代码支持;
	 * 
	 * @param securityManager
	 * @return
	 */
	// @Bean
	// public AuthorizationAttributeSourceAdvisor
	// authorizationAttributeSourceAdvisor(
	// SecurityManager securityManager) {
	// AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor =
	// new AuthorizationAttributeSourceAdvisor();
	// authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
	// return authorizationAttributeSourceAdvisor;
	// }

	/**
	 * cacheManager 缓存 redis实现
	 * <p>
	 * 使用的是shiro-redis开源插件
	 * 
	 * @return
	 */
	@Bean
	public ShiroRedisCacheManager getCacheManager() {
		return new ShiroRedisCacheManager();
	}

	/**
	 * cookie对象;
	 * 
	 * @return
	 */
	// public SimpleCookie rememberMeCookie() {
	// // 这个参数是cookie的名称，对应前端的checkbox的name = rememberMe
	// SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
	// // <!-- 记住我cookie生效时间30天 ,单位秒;-->
	// simpleCookie.setMaxAge(2592000);
	// return simpleCookie;
	// }
	//
	// /**
	// * cookie管理对象;记住我功能
	// *
	// * @return
	// */
	// public CookieRememberMeManager rememberMeManager() {
	// CookieRememberMeManager cookieRememberMeManager = new
	// CookieRememberMeManager();
	// cookieRememberMeManager.setCookie(rememberMeCookie());
	// // rememberMe cookie加密的密钥 建议每个项目都不一样 默认AES算法 密钥长度(128 256 512 位)
	// cookieRememberMeManager.setCipherKey(Base64
	// .decode("3AvVhmFLUs0KTA3Kprsdag=="));
	// return cookieRememberMeManager;
	// }

	// @Bean(name = "shiroDialect")
	// public ShiroDialect shiroDialect(){
	// return new ShiroDialect();
	// }

}
